using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using ProjectMercury;
using ProjectMercury.Emitters;
using ProjectMercury.Modifiers;
using ProjectMercury.Renderers;

namespace xna_game_engine.source
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class ParticleSystem : Microsoft.Xna.Framework.GameComponent
    {
        private Emitter mBasicEmitter;
        private ConeEmitter mConeEmitter;
        private PolygonEmitter mPolyEmitter;
        public ParticleSystem(Game game) : base(game)
        {
            // Basic Emitter setup
            mBasicEmitter = new Emitter();
            mBasicEmitter.Budget = 5000;
            mBasicEmitter.ReleaseQuantity = 200;
            mBasicEmitter.ReleaseScale = new VariableFloat { Anchor = 1.0f, Variation = 10.0f };
            mBasicEmitter.ReleaseSpeed = new VariableFloat { Anchor = 1.0f, Variation = 100.0f };
            mBasicEmitter.ReleaseColour = Color.Goldenrod.ToVector3();
            mBasicEmitter.ReleaseOpacity = new VariableFloat { Anchor = 0.2f, Variation = 1.0f };
            mBasicEmitter.Term = 0.4f;
            mBasicEmitter.Initialize();

            // Cone Emitter Setup
            mConeEmitter = new ConeEmitter();
            mConeEmitter.Budget = 5000;
            mConeEmitter.ReleaseQuantity = 100;
            mConeEmitter.ReleaseScale = new VariableFloat { Anchor = 1.0f, Variation = 10.0f };
            mConeEmitter.ReleaseSpeed = new VariableFloat { Anchor = 1.0f, Variation = 50.0f };
            mConeEmitter.ReleaseColour = Color.Goldenrod.ToVector3();
            mConeEmitter.ReleaseOpacity = new VariableFloat { Anchor = 0.2f, Variation = 1.0f };
            mConeEmitter.Term = 0.8f;
            // Cone specific
            mConeEmitter.ConeAngle = 0.5f;
            mConeEmitter.Direction = -1.5f;
            mConeEmitter.Initialize();

            mPolyEmitter = new PolygonEmitter();
            mPolyEmitter.ReleaseColour = Color.Yellow.ToVector3();
            mPolyEmitter.Budget = 5000;
            mPolyEmitter.ReleaseQuantity = 200;
            mPolyEmitter.ReleaseScale = new VariableFloat { Anchor = 1.0f, Variation = 5.0f };
            mPolyEmitter.ReleaseSpeed = new VariableFloat { Anchor = 1.0f, Variation = 20.0f };
            mPolyEmitter.ReleaseOpacity = new VariableFloat { Anchor = 0.2f, Variation = 1.0f };
            mPolyEmitter.Term = 0.15f;
            mPolyEmitter.Close = false;
            mPolyEmitter.Initialize();
        }

        public void LoadContent(ContentManager cm)
        {
            mBasicEmitter.ParticleTexture = cm.Load<Texture2D>("sprites\\particles\\circle");
            mConeEmitter.ParticleTexture = cm.Load<Texture2D>("sprites\\particles\\circle");
            mPolyEmitter.ParticleTexture = cm.Load<Texture2D>("sprites\\particles\\circle");
        }

        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            mBasicEmitter.Update((float)gameTime.TotalGameTime.TotalSeconds, (float)gameTime.ElapsedGameTime.TotalSeconds);
            mConeEmitter.Update((float)gameTime.TotalGameTime.TotalSeconds, (float)gameTime.ElapsedGameTime.TotalSeconds);
            mPolyEmitter.Update((float)gameTime.TotalGameTime.TotalSeconds, (float)gameTime.ElapsedGameTime.TotalSeconds);
            base.Update(gameTime);
        }

        public void Draw()
        {
            GameSystems.Graphics.EndSprites();
            GameSystems.Graphics.BeginSprites(SpriteBlendMode.Additive, SpriteSortMode.Deferred, SaveStateMode.None, Matrix.Identity);

            if (mBasicEmitter.ParticleTexture != null && mBasicEmitter.ActiveParticlesCount > 0)
            {
                // Calculate the source rectangle and origin offset of the Particle texture...
                Rectangle source = new Rectangle(0, 0, mBasicEmitter.ParticleTexture.Width, mBasicEmitter.ParticleTexture.Height);
                Vector2 origin = new Vector2(source.Width / 2f, source.Height / 2f);

                for (int i = 0; i < mBasicEmitter.ActiveParticlesCount; i++)
                {
                    Particle particle = mBasicEmitter.Particles[i];

                    float scale = particle.Scale / mBasicEmitter.ParticleTexture.Width;

                    GameSystems.Graphics.DrawImage(mBasicEmitter.ParticleTexture, particle.Position, source, new Color(particle.Colour), particle.Rotation, origin, scale, SpriteEffects.None, 0f);
                }
            }

            if (mConeEmitter.ParticleTexture != null && mConeEmitter.ActiveParticlesCount > 0)
            {
                // Calculate the source rectangle and origin offset of the Particle texture...
                Rectangle source = new Rectangle(0, 0, mConeEmitter.ParticleTexture.Width, mConeEmitter.ParticleTexture.Height);
                Vector2 origin = new Vector2(source.Width / 2f, source.Height / 2f);

                for (int i = 0; i < mConeEmitter.ActiveParticlesCount; i++)
                {
                    Particle particle = mConeEmitter.Particles[i];

                    float scale = particle.Scale / mBasicEmitter.ParticleTexture.Width;

                    GameSystems.Graphics.DrawImage(mConeEmitter.ParticleTexture, particle.Position, source, new Color(particle.Colour), particle.Rotation, origin, scale, SpriteEffects.None, 0f);
                }
            }

            // Particle test
            if (mPolyEmitter.ParticleTexture != null && mPolyEmitter.ActiveParticlesCount > 0)
            {
                // Calculate the source rectangle and origin offset of the Particle texture...
                Rectangle source = new Rectangle(0, 0, mPolyEmitter.ParticleTexture.Width, mPolyEmitter.ParticleTexture.Height);
                Vector2 origin = new Vector2(source.Width / 2f, source.Height / 2f);

                for (int i = 0; i < mPolyEmitter.ActiveParticlesCount; i++)
                {
                    Particle particle = mPolyEmitter.Particles[i];

                    float scale = particle.Scale / mPolyEmitter.ParticleTexture.Width;
                    GameSystems.Graphics.DrawImage(mConeEmitter.ParticleTexture, particle.Position, source, new Color(particle.Colour), particle.Rotation, origin, scale, SpriteEffects.None, 0f);
                } 
            }
            GameSystems.Graphics.EndSprites();
            GameSystems.Graphics.BeginSprites();
        }

        public void BasicTrigger(Vector2 pos, Color color)
        {
            mBasicEmitter.ReleaseColour = color.ToVector3();
            mBasicEmitter.Trigger(pos);
        }
        public void ConeTrigger(Vector2 pos, Color color)
        {
            mConeEmitter.ReleaseColour = color.ToVector3();
            mConeEmitter.Trigger(pos);
        }
        public void PolyTrigger(Vector2 pos, Color color, float rot, float distance)
        {
            mPolyEmitter.ReleaseColour = color.ToVector3();
            mPolyEmitter.Rotation = rot;
            mPolyEmitter.Points = new PolygonPointCollection { Vector2.Zero, new Vector2(distance, 0.0f) };
            mPolyEmitter.Trigger(pos);
        }
    }
}